Camera源码分析

本篇我们主要针对HAL1.0介绍Camera提供的服务,分析Camera打开过程。

打开过程

这里我们看下CameraService的connect。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
//最终打开摄像头会调用Service的connect
status_t CameraService::connect(
const sp<ICameraClient>& cameraClient,
int cameraId,
const String16& clientPackageName,
int clientUid,
/*out*/
sp<ICamera>& device) {

String8 clientName8(clientPackageName);
int callingPid = getCallingPid();//获取调用者的进程id

LOG1("CameraService::connect E (pid %d \"%s\", id %d)", callingPid,
clientName8.string(), cameraId);

status_t status = validateConnect(cameraId, /*inout*/clientUid);//连接之前的校验
if (status != OK) {
return status;
}


sp<Client> client;
{
Mutex::Autolock lock(mServiceLock);//连接过程要加锁
sp<BasicClient> clientTmp;
if (!canConnectUnsafe(cameraId, clientPackageName,
cameraClient->asBinder(),
/*out*/clientTmp)) {//确保本次连接是安全的
return -EBUSY;
} else if (client.get() != NULL) {
device = static_cast<Client*>(clientTmp.get());
return OK;
}

int facing = -1;
int deviceVersion = getDeviceVersion(cameraId, &facing);//获取设备版本

// If there are other non-exclusive users of the camera,
// this will tear them down before we can reuse the camera
if (isValidCameraId(cameraId)) {//有效的摄像头id
// transition from PRESENT -> NOT_AVAILABLE
updateStatus(ICameraServiceListener::STATUS_NOT_AVAILABLE,
cameraId);//更新状态
}

switch(deviceVersion) {//根据设备版本 创建Client对象
case CAMERA_DEVICE_API_VERSION_1_0:
client = new CameraClient(this, cameraClient,
clientPackageName, cameraId,
facing, callingPid, clientUid, getpid());
break;
case CAMERA_DEVICE_API_VERSION_2_0:
case CAMERA_DEVICE_API_VERSION_2_1:
case CAMERA_DEVICE_API_VERSION_3_0:
client = new Camera2Client(this, cameraClient,
clientPackageName, cameraId,
facing, callingPid, clientUid, getpid(),
deviceVersion);
break;
case -1:
ALOGE("Invalid camera id %d", cameraId);
return BAD_VALUE;
default:
ALOGE("Unknown camera device HAL version: %d", deviceVersion);
return INVALID_OPERATION;
}

status_t status = connectFinishUnsafe(client, client->getRemote());//会调用client的initialize方法进行初始化
if (status != OK) {
// this is probably not recoverable.. maybe the client can try again
// OK: we can only get here if we were originally in PRESENT state
updateStatus(ICameraServiceListener::STATUS_PRESENT, cameraId);
return status;
}

mClient[cameraId] = client;//保存client
LOG1("CameraService::connect X (id %d, this pid is %d)", cameraId,
getpid());
}
// important: release the mutex here so the client can call back
// into the service from its destructor (can be at the end of the call)

device = client;//Client作为ICamera接口返回给客户端 客户端可以使用该接口跟Camera进行交互
return OK;
}

客户端在打开摄像头时最终会调用到这个方法,并未其创建了CameraClient对象,这里针对API为1.0时介绍,所以重点关注CameraClient的创建过程及初始化流程,看看它是如何提供摄像头的服务的。在创建完client对象后,在connectFinishUnsafe会对其进行初始化,即调用client->initialize(mModule)方法这个mModule即是底层的Camera模块,其初始化是在CameraService的onFirstRef中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
void CameraService::onFirstRef()
{
LOG1("CameraService::onFirstRef");

BnCameraService::onFirstRef();

if (hw_get_module(CAMERA_HARDWARE_MODULE_ID,
(const hw_module_t **)&mModule) < 0) {//获取Camera HAL层的Module
ALOGE("Could not load camera HAL module");
mNumberOfCameras = 0;
}
else {
ALOGI("Loaded \"%s\" camera module", mModule->common.name);
mNumberOfCameras = mModule->get_number_of_cameras();//通过module的接口获取摄像头数目
if (mNumberOfCameras > MAX_CAMERAS) {
ALOGE("Number of cameras(%d) > MAX_CAMERAS(%d).",
mNumberOfCameras, MAX_CAMERAS);
mNumberOfCameras = MAX_CAMERAS;
}
for (int i = 0; i < mNumberOfCameras; i++) {
setCameraFree(i);
}

if (mModule->common.module_api_version >=
CAMERA_MODULE_API_VERSION_2_1) {
mModule->set_callbacks(this);//设置摄像头状态回调 onDeviceStatusChanged
}

CameraDeviceFactory::registerService(this);
}
}

status_t CameraClient::initialize(camera_module_t *module) {
int callingPid = getCallingPid();
status_t res;

LOG1("CameraClient::initialize E (pid %d, id %d)", callingPid, mCameraId);

// Verify ops permissions
res = startCameraOps();//校验权限
if (res != OK) {
return res;
}

char camera_device_name[10];
snprintf(camera_device_name, sizeof(camera_device_name), "%d", mCameraId);

mHardware = new CameraHardwareInterface(camera_device_name);//创建Camera的硬件接口对象
res = mHardware->initialize(&module->common);//初始化该对象 包括打开摄像头模块 初始化预览窗口回调等
if (res != OK) {
ALOGE("%s: Camera %d: unable to initialize device: %s (%d)",
__FUNCTION__, mCameraId, strerror(-res), res);
mHardware.clear();
return NO_INIT;
}

mHardware->setCallbacks(notifyCallback,
dataCallback,
dataCallbackTimestamp,
(void *)mCameraId);//设置时间回调和数据回调

// Enable zoom, error, focus, and metadata messages by default
enableMsgType(CAMERA_MSG_ERROR | CAMERA_MSG_ZOOM | CAMERA_MSG_FOCUS |
CAMERA_MSG_PREVIEW_METADATA | CAMERA_MSG_FOCUS_MOVE);

LOG1("CameraClient::initialize X (pid %d, id %d)", callingPid, mCameraId);
return OK;
}

initialize这个方法比较重要,它主要做了下面几件事:

  1. 创建CameraHardwareInterface对象,CameraHardwareInterface是HAL层的接口对象,CameraClient的所提供的服务最终会转向这个接口对象。在HAL1.0中,这个对象是同HAL层进行交互的桥梁。

  2. 初始化该接口对象,包括打开摄像头模块 初始化预览窗口回调等

  3. 调用setCallbacks来设置回调,比如数据的回调,通知消息的回调,这些回调方法都是在CameraClient中实现,即底层会将相关的消息或者数据通过这些方法回调给上层。

我们看看CameraHardwareInterface初始化过程

1
2
3
4
5
6
7
8
9
10
11
12
status_t initialize(hw_module_t *module)
{
ALOGI("Opening camera %s", mName.string());
int rc = module->methods->open(module, mName.string(),
(hw_device_t **)&mDevice);//通过HAL的接口打开摄像头 同时构造mDevice
if (rc != OK) {
ALOGE("Could not open camera %s: %d", mName.string(), rc);
return rc;
}
initHalPreviewWindow();//初始化预览窗口
return rc;
}

这个方法纯粹只是打开了HAL module的open方法,会调用底层驱动的打开方法,这个方法会返回一个mDevice,这个mDevice是HAL层定义的camera_device_t结构

1
2
3
4
5
6
7
8
9
10
typedef struct camera_device {  
/**
* camera_device.common.version must be in the range
* HARDWARE_DEVICE_API_VERSION(0,0)-(1,FF). CAMERA_DEVICE_API_VERSION_1_0 is
* recommended.
*/
hw_device_t common;
camera_device_ops_t *ops;
void *priv;
} camera_device_t; //对应的是1.0的DEVICE_API

camera_device_ops_t是摄像头定义的一系列服务接口,如int (*take_picture)(struct camera_device *);
CameraHardwareInterface层向上提供的服务都是通过HAL层的这些接口完成。

接着初始化HAL的预览窗口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
void initHalPreviewWindow()
{
mHalPreviewWindow.nw.cancel_buffer = __cancel_buffer;
mHalPreviewWindow.nw.lock_buffer = __lock_buffer;
mHalPreviewWindow.nw.dequeue_buffer = __dequeue_buffer;
mHalPreviewWindow.nw.enqueue_buffer = __enqueue_buffer;
mHalPreviewWindow.nw.set_buffer_count = __set_buffer_count;
mHalPreviewWindow.nw.set_buffers_geometry = __set_buffers_geometry;
mHalPreviewWindow.nw.set_crop = __set_crop;
mHalPreviewWindow.nw.set_timestamp = __set_timestamp;
mHalPreviewWindow.nw.set_usage = __set_usage;
mHalPreviewWindow.nw.set_swap_interval = __set_swap_interval;

mHalPreviewWindow.nw.get_min_undequeued_buffer_count =
__get_min_undequeued_buffer_count;
}

这个mHalPreviewWindow是个camera_preview_window,它的定义如下

1
2
3
4
struct camera_preview_window {
struct preview_stream_ops nw;
void *user;
};

这里的preview_stream_ops它是一系列关于本地窗口ANativeWindow的操作方法的接口。

回调的设置是通过setCallbacks完成

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/** Set the notification and data callbacks */
void setCallbacks(notify_callback notify_cb,
data_callback data_cb,
data_callback_timestamp data_cb_timestamp,
void* user)//设置回调消息和数据回调
{
mNotifyCb = notify_cb;
mDataCb = data_cb;
mDataCbTimestamp = data_cb_timestamp;
mCbUser = user;

ALOGV("%s(%s)", __FUNCTION__, mName.string());

if (mDevice->ops->set_callbacks) {
mDevice->ops->set_callbacks(mDevice,
__notify_cb,
__data_cb,
__data_cb_timestamp,
__get_memory,
this);
}
}

参数notify_cb,data_cb是CameraClient的方法,这里首先对其进行了保存,并将CameraHardwareInterface自身的的__notify_cb,__data_cb等通过HAL层设置给底层驱动,这么说当数据或者消息需要通知到上层时在CameraHardwareInterface的__notify_cb,__data_cb方法是需要再转发给CameraClient的notify_cb和data_cb的。

HAL层的实现,我们这里看的是rk29的相关实现

/android4.4/hardware/rk29/camera/CameraHal_Module.cpp

这个文件中定义了HAL层的module,即HAL_MODULE_INFO_SYM,这是所有HAL层必须定义的。所有的硬件对应的module结构必须以
hw_module_t作为其第一个成员,一般就是common成员。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
static struct hw_module_methods_t camera_module_methods = {
open: camera_device_open
};

camera_module_t HAL_MODULE_INFO_SYM = {
common: {
tag: HARDWARE_MODULE_TAG,
version_major: ((CONFIG_CAMERAHAL_VERSION&0xff00)>>8),
version_minor: CONFIG_CAMERAHAL_VERSION&0xff,
id: CAMERA_HARDWARE_MODULE_ID,
name: CAMERA_MODULE_NAME,
author: "RockChip",
methods: &camera_module_methods,
dso: NULL, /* remove compilation warnings */
reserved: {0}, /* remove compilation warnings */
},
get_number_of_cameras: camera_get_number_of_cameras,
get_camera_info: camera_get_camera_info,
};

我们看到open方法调用的是camera_device_open,我们看看这个方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
int camera_device_open(const hw_module_t* module, const char* name,
hw_device_t** device)
{
int rv = 0;
int cameraid;
rk_camera_device_t* camera_device = NULL;
camera_device_ops_t* camera_ops = NULL;
android::CameraHal* camera = NULL;

android::Mutex::Autolock lock(gCameraHalDeviceLock);

LOGI("camera_device open");

if (name != NULL) {
cameraid = atoi(name);//将name变为id

if(cameraid > gCamerasNumber) {//摄像头的id不能大于摄像头的数目 id可能只是个索引
LOGE("camera service provided cameraid out of bounds, "
"cameraid = %d, num supported = %d",
cameraid, gCamerasNumber);
rv = -EINVAL;
goto fail;
}

if(gCamerasOpen >= CAMERAS_SUPPORTED_SIMUL_MAX) {
LOGE("maximum number(%d) of cameras already open",gCamerasOpen);
rv = -ENOMEM;
goto fail;
}

camera_device = (rk_camera_device_t*)malloc(sizeof(*camera_device));//分配一个rk_camera_device_t结构
if(!camera_device) {
LOGE("camera_device allocation fail");
rv = -ENOMEM;
goto fail;
}

camera_ops = (camera_device_ops_t*)malloc(sizeof(*camera_ops));//分配camera_device_ops_t 结构
if(!camera_ops) {
LOGE("camera_ops allocation fail");
rv = -ENOMEM;
goto fail;
}

memset(camera_device, 0, sizeof(*camera_device));
memset(camera_ops, 0, sizeof(*camera_ops));

camera_device->base.common.tag = HARDWARE_DEVICE_TAG;
camera_device->base.common.version = 0;
camera_device->base.common.module = (hw_module_t *)(module);
camera_device->base.common.close = camera_device_close;
camera_device->base.ops = camera_ops;

camera_ops->set_preview_window = camera_set_preview_window;
camera_ops->set_callbacks = camera_set_callbacks;
camera_ops->enable_msg_type = camera_enable_msg_type;
camera_ops->disable_msg_type = camera_disable_msg_type;
camera_ops->msg_type_enabled = camera_msg_type_enabled;
camera_ops->start_preview = camera_start_preview;
camera_ops->stop_preview = camera_stop_preview;
camera_ops->preview_enabled = camera_preview_enabled;
camera_ops->store_meta_data_in_buffers = camera_store_meta_data_in_buffers;
camera_ops->start_recording = camera_start_recording;
camera_ops->stop_recording = camera_stop_recording;
camera_ops->recording_enabled = camera_recording_enabled;
camera_ops->release_recording_frame = camera_release_recording_frame;
camera_ops->auto_focus = camera_auto_focus;
camera_ops->cancel_auto_focus = camera_cancel_auto_focus;
camera_ops->take_picture = camera_take_picture;
camera_ops->cancel_picture = camera_cancel_picture;
camera_ops->set_parameters = camera_set_parameters;
camera_ops->get_parameters = camera_get_parameters;
camera_ops->put_parameters = camera_put_parameters;
camera_ops->send_command = camera_send_command;
camera_ops->release = camera_release;
camera_ops->dump = camera_dump;

*device = &camera_device->base.common;

// -------- RockChip specific stuff --------

camera_device->cameraid = cameraid;

camera = new android::CameraHal(cameraid);

if(!camera) {
LOGE("Couldn't create instance of CameraHal class");
rv = -ENOMEM;
goto fail;
}

gCameraHals[cameraid] = camera;
gCamerasOpen++;
}

return rv;

fail:
if(camera_device) {
free(camera_device);
camera_device = NULL;
}
if(camera_ops) {
free(camera_ops);
camera_ops = NULL;
}
if(camera) {
delete camera;
camera = NULL;
}
*device = NULL;
return rv;
}

这个方法主要做下面几件事:

  1. 创建一个rk_camera_device_t 用来描述Camera设备,它的定义是只是比camera_device_t多了一个cameraid,是对camera_device_t的拓展。
1
2
3
4
typedef struct rk_camera_device {
camera_device_t base; //定义在camera.h中
int cameraid;
} rk_camera_device_t;
  1. 创建camera_device_ops_t 用来描述Camera驱动提供的服务方法,在这里对其进行初始化,即指定了HAL层提供服务的具体方法。我们知道camera_device_ops_t是保存在camera_device_t结构中的。

  2. 创建android::CameraHal对象,这个对象通过和摄像头驱动的交互来提供具体的服务,比如预览,拍照。

预览数据的传递

下面为了进一步熟悉这个流程,我们看看摄像头的预览数据是如何在整个系统中进行传递的。

java层调用setPreviewCallback设置预览回调PreviewCallback,将其保存在mPreviewCallback中,接着调用jni层的
setHasPreviewCallback,即android_hardware_Camera_setHasPreviewCallback

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//设置预览回调
static void android_hardware_Camera_setHasPreviewCallback(JNIEnv *env, jobject thiz, jboolean installed, jboolean manualBuffer)
{
ALOGV("setHasPreviewCallback: installed:%d, manualBuffer:%d", (int)installed, (int)manualBuffer);
// Important: Only install preview_callback if the Java code has called
// setPreviewCallback() with a non-null value, otherwise we'd pay to memcpy
// each preview frame for nothing.
JNICameraContext* context;
sp<Camera> camera = get_native_camera(env, thiz, &context);
if (camera == 0) return;

// setCallbackMode will take care of setting the context flags and calling
// camera->setPreviewCallbackFlags within a mutex for us.
context->setCallbackMode(env, installed, manualBuffer);
}

可以看到这个方法并没有做什么处理,只是通过JNICameraContext 的setCallbackMode给Camera设置了一个回调标记mCamera->setPreviewCallbackFlags(CAMERA_FRAME_CALLBACK_FLAG_BARCODE_SCANNER);那么我们无法继续自顶向下进行分析,只能从底层进行分析。我们直接看底层CameraHal层预览相关的,在CameraHal::displayThread的实现中,当取到消息CMD_DISPLAY_FRAME会进行数据帧的绘制显示,这里面会调用由CameraHal::setCallbacks设置的回调mDataCb,它是这样调用的mDataCb(CAMERA_MSG_PREVIEW_FRAME, mPreviewMemory, queue_display_index,NULL,mCallbackCookie);//预览回调 回调给上层 显示了一帧数据这里的mCallbackCookie为上层CameraHardwareInterface对象,这里的消息类型为CAMERA_MSG_PREVIEW_FRAME。

还记得这个回调是在哪里进行设置的? 没错,是在CameraHardwareInterface中,即它的__data_cb方法我们看看这个方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
static void __data_cb(int32_t msg_type,
const camera_memory_t *data, unsigned int index,
camera_frame_metadata_t *metadata,
void *user)
{
ALOGV("%s", __FUNCTION__);
CameraHardwareInterface *__this =
static_cast<CameraHardwareInterface *>(user); //user就是CameraHardwareInterface,它是在setCallBacks时传过去的
sp<CameraHeapMemory> mem(static_cast<CameraHeapMemory *>(data->handle));//取到CameraHeapMemory,它内部有一组缓冲区
if (index >= mem->mNumBufs) {
ALOGE("%s: invalid buffer index %d, max allowed is %d", __FUNCTION__,
index, mem->mNumBufs);
return;
}
__this->mDataCb(msg_type, mem->mBuffers[index], metadata, __this->mCbUser);//index指定了当前显示的buffer的索引
}

这个方法最后通过mDataCb调用给CameraClient::dataCallback

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
void CameraClient::dataCallback(int32_t msgType,
const sp<IMemory>& dataPtr, camera_frame_metadata_t *metadata, void* user) {
LOG2("dataCallback(%d)", msgType);//数据回调

Mutex* lock = getClientLockFromCookie(user);
if (lock == NULL) return;
Mutex::Autolock alock(*lock);

CameraClient* client =
static_cast<CameraClient*>(getClientFromCookie(user));//这个user是CameraClient对象 是在setCallBacks时设置的
if (client == NULL) return;

if (!client->lockIfMessageWanted(msgType)) return;
if (dataPtr == 0 && metadata == NULL) {
ALOGE("Null data returned in data callback");
client->handleGenericNotify(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0);
return;
}

switch (msgType & ~CAMERA_MSG_PREVIEW_METADATA) {
case CAMERA_MSG_PREVIEW_FRAME:
client->handlePreviewData(msgType, dataPtr, metadata);//回调预览数据
break;
case CAMERA_MSG_POSTVIEW_FRAME:
client->handlePostview(dataPtr);
break;
case CAMERA_MSG_RAW_IMAGE:
client->handleRawPicture(dataPtr);
break;
case CAMERA_MSG_COMPRESSED_IMAGE:
client->handleCompressedPicture(dataPtr);
break;
default:
client->handleGenericData(msgType, dataPtr, metadata);
break;
}
}

当消息类型为CAMERA_MSG_PREVIEW_FRAME时调用clinet的handlePreviewData方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
// preview callback - frame buffer update
void CameraClient::handlePreviewData(int32_t msgType,
const sp<IMemory>& mem,
camera_frame_metadata_t *metadata) {//处理预览数据

ssize_t offset;
size_t size;
sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);

// local copy of the callback flags
int flags = mPreviewCallbackFlag;//预览的回调的flag 之前设置的为CAMERA_FRAME_CALLBACK_FLAG_BARCODE_SCANNER

// is callback enabled?
if (!(flags & CAMERA_FRAME_CALLBACK_FLAG_ENABLE_MASK)) {
// If the enable bit is off, the copy-out and one-shot bits are ignored
LOG2("frame callback is disabled");
mLock.unlock();
return;
}

// hold a strong pointer to the client
sp<ICameraClient> c = mRemoteCallback;//也就是BpCameraClient

// clear callback flags if no client or one-shot mode
if (c == 0 || (mPreviewCallbackFlag & CAMERA_FRAME_CALLBACK_FLAG_ONE_SHOT_MASK)) {
LOG2("Disable preview callback");
mPreviewCallbackFlag &= ~(CAMERA_FRAME_CALLBACK_FLAG_ONE_SHOT_MASK |
CAMERA_FRAME_CALLBACK_FLAG_COPY_OUT_MASK |
CAMERA_FRAME_CALLBACK_FLAG_ENABLE_MASK);
disableMsgType(CAMERA_MSG_PREVIEW_FRAME);
}

if (c != 0) {
// Is the received frame copied out or not?
if (flags & CAMERA_FRAME_CALLBACK_FLAG_COPY_OUT_MASK) {
LOG2("frame is copied");
copyFrameAndPostCopiedFrame(msgType, c, heap, offset, size, metadata);
} else {
LOG2("frame is forwarded");
mLock.unlock();
c->dataCallback(msgType, mem, metadata);
}
} else {
mLock.unlock();
}
}

这里的mRemoteCallback是什么呢?是在哪里进行初始化的呢?它是在CameraService::connect时创建CameraClient对象时传递过来的,CameraClient在继承自CameraService::Client,创建该对象会同时构造CameraService::Client,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
CameraClient::CameraClient(const sp<CameraService>& cameraService,
const sp<ICameraClient>& cameraClient,
const String16& clientPackageName,
int cameraId, int cameraFacing,
int clientPid, int clientUid,
int servicePid):
Client(cameraService, cameraClient, clientPackageName,
cameraId, cameraFacing, clientPid, clientUid, servicePid){
.....
}

CameraService::Client::Client(const sp<CameraService>& cameraService,
const sp<ICameraClient>& cameraClient,
const String16& clientPackageName,
int cameraId, int cameraFacing,
int clientPid, uid_t clientUid,
int servicePid) :
CameraService::BasicClient(cameraService, cameraClient->asBinder(),
clientPackageName,
cameraId, cameraFacing,
clientPid, clientUid,
servicePid)
{
int callingPid = getCallingPid();
LOG1("Client::Client E (pid %d, id %d)", callingPid, cameraId);

mRemoteCallback = cameraClient;//将客户端的BpCameraClinet 即Camera保存下来

cameraService->setCameraBusy(cameraId);
cameraService->loadSound();

LOG1("Client::Client X (pid %d, id %d)", callingPid, cameraId);
}

这里的sp& cameraClient 实际上就是我们本地Camera对象,它是作为我们的客户端的,
所以继承了BnCameraClient,后者又继承了ICameraClient,它也是一个binder对象。CameraService::Client对将连接的对象保存在其mRemoteCallback中作为回调。

知道了mRemoteCallback怎么来的,那么我们继续看handlePreviewData,在设置预览时我们设置了flag为
预览的回调的flag 之前设置的为CAMERA_FRAME_CALLBACK_FLAG_BARCODE_SCANNER,它默认是CAMERA_FRAME_CALLBACK_FLAG_NOOP即禁止回调的。所以最终是通过 c->dataCallback(msgType, mem, metadata)回调给Bp端的,即Camera::dataCallback

1
2
3
4
5
6
7
8
9
10
11
12
13
// callback from camera service when frame or image is ready
void Camera::dataCallback(int32_t msgType, const sp<IMemory>& dataPtr,
camera_frame_metadata_t *metadata)
{
sp<CameraListener> listener;
{
Mutex::Autolock _l(mLock);
listener = mListener;
}
if (listener != NULL) {
listener->postData(msgType, dataPtr, metadata);
}
}

这里的mListener是谁?调用到哪里去了?它是一个CameraListener类型的接口,原来在JNI层建立摄像头连接的时候会调用camera->setListener(context);这个listener即JNICameraContext,它是继承自CameraListener的。这么说postData应该是JNI层的,我们看看

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
void JNICameraContext::postData(int32_t msgType, const sp<IMemory>& dataPtr,
camera_frame_metadata_t *metadata)//post 预览数据
{
// VM pointer will be NULL if object is released
Mutex::Autolock _l(mLock);
JNIEnv *env = AndroidRuntime::getJNIEnv();
if (mCameraJObjectWeak == NULL) {
ALOGW("callback on dead camera object");
return;
}

int32_t dataMsgType = msgType & ~CAMERA_MSG_PREVIEW_METADATA;

// return data based on callback type
switch (dataMsgType) {
case CAMERA_MSG_VIDEO_FRAME:
// should never happen
break;

// For backward-compatibility purpose, if there is no callback
// buffer for raw image, the callback returns null.
case CAMERA_MSG_RAW_IMAGE:
ALOGV("rawCallback");
if (mRawImageCallbackBuffers.isEmpty()) {
env->CallStaticVoidMethod(mCameraJClass, fields.post_event,
mCameraJObjectWeak, dataMsgType, 0, 0, NULL);
} else {
copyAndPost(env, dataPtr, dataMsgType);
}
break;

// There is no data.
case 0:
break;

default:
ALOGV("dataCallback(%d, %p)", dataMsgType, dataPtr.get());
copyAndPost(env, dataPtr, dataMsgType);
break;
}

// post frame metadata to Java
if (metadata && (msgType & CAMERA_MSG_PREVIEW_METADATA)) {
postMetadata(env, CAMERA_MSG_PREVIEW_METADATA, metadata);
}
}

msgType 是CAMERA_MSG_PREVIEW_FRAME,所以最终调用copyAndPost(env, dataPtr, dataMsgType);

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
void JNICameraContext::copyAndPost(JNIEnv* env, const sp<IMemory>& dataPtr, int msgType)
{
jbyteArray obj = NULL;

// allocate Java byte array and copy data
if (dataPtr != NULL) {
ssize_t offset;
size_t size;
sp<IMemoryHeap> heap = dataPtr->getMemory(&offset, &size);
ALOGV("copyAndPost: off=%ld, size=%d", offset, size);
uint8_t *heapBase = (uint8_t*)heap->base();

if (heapBase != NULL) {
const jbyte* data = reinterpret_cast<const jbyte*>(heapBase + offset);//从heap从取数据

if (msgType == CAMERA_MSG_RAW_IMAGE) {
obj = getCallbackBuffer(env, &mRawImageCallbackBuffers, size);
} else if (msgType == CAMERA_MSG_PREVIEW_FRAME && mManualBufferMode) {//走了这里
obj = getCallbackBuffer(env, &mCallbackBuffers, size);

if (mCallbackBuffers.isEmpty()) {
ALOGV("Out of buffers, clearing callback!");
mCamera->setPreviewCallbackFlags(CAMERA_FRAME_CALLBACK_FLAG_NOOP);
mManualCameraCallbackSet = false;

if (obj == NULL) {
return;
}
}
} else {
ALOGV("Allocating callback buffer");
obj = env->NewByteArray(size);
}

if (obj == NULL) {
ALOGE("Couldn't allocate byte array for JPEG data");
env->ExceptionClear();
} else {
env->SetByteArrayRegion(obj, 0, size, data);//设置预览数据
}
} else {
ALOGE("image heap is NULL");
}
}

// post image data to Java
env->CallStaticVoidMethod(mCameraJClass, fields.post_event,
mCameraJObjectWeak, msgType, 0, 0, obj);//post 图像数据给java层
if (obj) {
env->DeleteLocalRef(obj);
}
}

最终是调用CallStaticVoidMethod将数据送到java层的 fields.post_event注册为

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
fields.post_event = env->GetStaticMethodID(clazz, "postEventFromNative",
"(Ljava/lang/Object;IIILjava/lang/Object;)V");
```

那么应该是调用了java层的postEventFromNative的方法,这里obj保存了图像数据。

```c++
private static void postEventFromNative(Object camera_ref,
int what, int arg1, int arg2, Object obj)
{
Camera c = (Camera)((WeakReference)camera_ref).get();
if (c == null)
return;

if (c.mEventHandler != null) {
Message m = c.mEventHandler.obtainMessage(what, arg1, arg2, obj);//通过mEventHandler发送消息
c.mEventHandler.sendMessage(m);
}
}

最终是通过EventHandler来进行的,这里的mEventHandler是在构造Java层的Camera时创建的,我们直接看其对消息的处理

private class EventHandler extends Handler
{
    private Camera mCamera;

    public EventHandler(Camera c, Looper looper) {
        super(looper);
        mCamera = c;
    }

    @Override
    public void handleMessage(Message msg) {
        switch(msg.what) {
        ....
        case CAMERA_MSG_PREVIEW_FRAME:
            PreviewCallback pCb = mPreviewCallback;
            if (pCb != null) {
                if (mOneShot) {
                    // Clear the callback variable before the callback
                    // in case the app calls setPreviewCallback from
                    // the callback function
                    mPreviewCallback = null;
                } else if (!mWithBuffer) {
                    // We're faking the camera preview mode to prevent
                    // the app from being flooded with preview frames.
                    // Set to oneshot mode again.
                    setHasPreviewCallback(true, false);
                }
                pCb.onPreviewFrame((byte[])msg.obj, mCamera);//会通过这里回调给上层应用
            }
            return;

        case CAMERA_MSG_POSTVIEW_FRAME:
            if (mPostviewCallback != null) {
                mPostviewCallback.onPictureTaken((byte[])msg.obj, mCamera);
            }
            return;
        ......
        
        }
    }
}

看到对CAMERA_MSG_PREVIEW_FRAME消息的处理,这个mPreviewCallback是我们设置的预览回调,最终调用onPreviewFrame回调给应用。

坚持原创技术分享,您的支持将鼓励我继续创作!